<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service;

use app\enum\CodeEnum;
use app\enum\CommonEnum;
use app\enum\QqEnum;
use app\model\AccountPortModel;
use app\model\ClientAccountModel;
use app\model\ClientAccountOperationModel;
use app\model\ProjectAccountModel;
use app\service\client\AccountService;
use proxy\Client;
use think\facade\Cache;

class BaseService
{
    /**
     * @var array 错误消息
     */
    protected static array $error = [];

    /**
     * 获取错误消息.
     *
     * @param null|mixed $num
     * @return array|mixed|string
     */
    public static function getError($num = null)
    {
        if (is_null($num)) {
            return self::$error;
        }
        return self::$error[intval($num)] ?? CodeEnum::CODE_MESSAGE[CodeEnum::ERROR];
    }

    /**
     * 获取媒体显帐和现金消耗.
     * @param $clientId int 客户id
     * @param $mediaId int 媒体id
     * @param $date int 日期
     * @return int
     */
    public static function getClientCost(int $clientId, int $mediaId, int $date)
    {
        $cost = [
            'cost' => 0,
            'cash_cost' => 0,
        ];
        if ($mediaId == 1) {
            $cost = ClientAccountModel::alias('a')
                ->leftJoin(['habo_oe_advertiser_daily_stat' => 'b'], 'a.advertiser_id=b.advertiser_id')
                ->where('a.client_id', $clientId)
                ->where('a.media_id', $mediaId)
                ->where('b.stat_date', $date)
                ->field('sum(cost+company_wallet_cost) as cost,sum(cash_cost+company_wallet_cost) as cash_cost')
                ->find();
        } elseif ($mediaId == 2) {
            $cost = ClientAccountModel::alias('a')
                ->leftJoin(['habo_ks_advertiser_daily_stat' => 'b'], 'a.advertiser_id=b.advertiser_id')
                ->where('a.client_id', $clientId)
                ->where('a.media_id', $mediaId)
                ->where('b.stat_date', $date)
                ->field('sum(daily_charge) as cost,sum(real_charged) as cash_cost')
                ->find();
        } elseif ($mediaId == 5) {
            $costData = ClientAccountModel::alias('a')
                ->leftJoin(['habo_qq_advertiser_daily_stat' => 'b'], 'a.advertiser_id=b.advertiser_id')
                ->where('a.client_id', $clientId)
                ->where('a.media_id', $mediaId)
                ->where('b.stat_date', $date)
                ->select();
            foreach ($costData as $item) {
                $paid = $item['paid'] / 100;
                if ($item['fund_type'] == QqEnum::FUND_TYPE_CASH) {// 现金消耗
                    $cost['cost'] += $paid;
                    $cost['cash_cost'] += $paid;
                } elseif ($item['fund_type'] == QqEnum::FUND_TYPE_VIRTUAL) {// 补偿虚拟金消耗
                    $cost['cost'] += $paid;
                } elseif ($item['fund_type'] == QqEnum::FUND_TYPE_ROLL) {// 固定信用金消耗
                    $cost['cost'] += $paid;
                    $cost['cash_cost'] += $paid;
                }
            }
        }
        return $cost;
    }

    /**
     * 发送请求.
     *
     * @param string $serviceName 服务名
     * @param string $serviceUrl 服务链接
     * @param array $param 请求参数
     * @param string $method 请求方式
     * @param array $header 请求头
     * @param string $type 回调类型
     * @return bool|mixed
     */
    public static function send(string $serviceName = '', string $serviceUrl = '', array $param = [], string $method = 'get', array $header = [], string $type = '')
    {
        if (! $serviceName || ! $serviceUrl) {
            return self::setError('请求参数错误');
        }
        if (! $type) {
            $type = Client::RETURN_TYPE;
        }
        try {
            $client = new Client();
            return call_user_func_array([$client, $method], [$serviceName, $serviceUrl, $param])->setHeader($header)->exec($type);
        } catch (\Exception $e) {
            return self::setError($e->getMessage());
        }
    }

    /**
     * 获取分页账户.
     * @deprecated
     */
    public static function getLimitAdvertiserIds(int $mediaId, int $num = 0): array
    {
        $advertiserIds = ClientAccountModel::where('media_id', $mediaId)->column('advertiser_id');
        if ($advertiserIds) {
            $limit = ceil(count($advertiserIds) / CommonEnum::SHELL_NUM);
            $advertiserIds = array_slice($advertiserIds, intval($num * $limit), (int) $limit);
        }
        return $advertiserIds;
    }

    /**
     * 获取账户信息.
     * @param string $advertiserId 账户ID
     * @throws
     */
    public static function getClientAccountInfo(string $advertiserId = ''): array
    {
        $info = (new ClientAccountModel())->where('advertiser_id', $advertiserId)->field(true)->find();
        if (! $info) {
            return [];
        }
        $info = $info->toArray();
        // 查询账户运营
        $staffId = ClientAccountOperationModel::where('advertiser_id', $advertiserId)->value('staff_id');
        $projectId = ProjectAccountModel::where('account_id', $info['id'])->value('project_id');
        $info['staff_id'] = $staffId ?: 0;
        $info['project_id'] = $projectId ?: 0;
        if ($info['media_id'] == CommonEnum::KS_MEDIA) {
            $info['user_id'] = AccountService::getKsUserId($advertiserId) ?: 0;
        }
        $productId = AccountPortModel::where('advertiser_id', $advertiserId)->value('product_id');
        $info['product_id'] = intval($productId ?: 0);

        return $info;
    }

    /**
     * 加锁
     *
     * @param string $key 键名
     * @param mixed $value 缓存值
     * @param int $expire 过期时间
     */
    public static function lock(string $key, $value, int $expire = 300): bool
    {
        if (! $key) {
            return false;
        }
        $redis = Cache::store('redis')->handler();
        if (! $redis->setnx($key, $value)) {
            return false;
        }
        if ($expire) {
            $redis->expire($key, $expire);
        }
        return true;
    }

    /**
     * 设置错误消息.
     *
     * @return false
     */
    protected static function setError(string $msg = ''): bool
    {
        array_unshift(self::$error, $msg);
        return false;
    }

    /**
     * 解锁
     *
     * @return true
     */
    protected static function unlock(string $key = ''): bool
    {
        if ($key) {
            Cache::store('redis')->handler()->del($key);
        }
        return true;
    }
}
